#pragma once

#include <iostream>
#include <unistd.h>

#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "../comm/util.hpp"
#include "../comm/log.hpp"
using namespace ns_util;

namespace ns_compiler
{
    using namespace ns_util;
    using namespace ns_log;

    class Compiler
    {
    public: // 默认成员函数
        Compiler() {}
        ~Compiler() {}

        static bool Compile(const std::string& file_name) // 预编译
        {
            pid_t pid = fork();
            if(pid < 0) { 
                // fork失败
                LOG(ERROR) << "内部错误: 创建子进程fork()失败." << "\n";
                return false;
            } else if(pid == 0) { 
                // 子进程 ↓
                umask(0);
                int _stderr = open(PathUtil::CompileError(file_name).c_str(), O_WRONLY | O_CREAT, 0644);
                if(_stderr < 0) {
                    LOG(WARNING) << "形成stderr文件失败" << "\n";
                    exit(1);
                }

                // 重定向 “标准错误” 到_stderr
                dup2(_stderr, 2);

                // 编译
                if(execlp("g++", "g++", "-o", PathUtil::Exe(file_name).c_str(),\
                        PathUtil::Src(file_name).c_str(), "-D", "COMPILER_ONLINE", "-std=c++11", nullptr) < 0) // -D 用于定义宏
                {
                    LOG(ERROR) << "启动编译器g++失败, possible parameter error." << "\n";
                    exit(2);
                }
            } else { 
                // 父进程 ↓
                // 等待子进程结束
                waitpid(pid, NULL, 0);
                if(FileUtil::IsFileExist(PathUtil::Exe(file_name))) {
                    LOG(INFO) << PathUtil::Src(file_name) << " 编译成功！" << "\n";
                    return true;
                } else {   
                    LOG(ERROR) << "编译失败，未形成可执行文件" << "\n";
                    return false;
                }
            }
            return false;
        }
    };
}